package com.ungao.framework.web.context;

import com.ungao.framework.convert.CaseConverter;
import com.ungao.framework.web.annotation.RequestParam;
import com.ungao.framework.web.exception.RequestException;
import com.ungao.servlet.HttpServletRequest;
import com.ungao.servlet.HttpServletResponse;
import com.ungao.servlet.MiniHttpServlet;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 请求分发类
 *
 * @author vic-ungao
 */
public class MiniDispatcherJDKServlet extends MiniHttpServlet {

    /**
     * 应用上下文
     */
    private WebApplicationContext applicationContext;

    @Override
    protected void dispatcher(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String uri = request.getRequestURI().getPath();
        uri = uri.replaceAll("/+", "/");

        //处理是否存在请求地址
        if (!this.applicationContext.hasUri(uri)) {
            response.sendError("404 Not Found!!");
            return;
        }

        //获取请求地址对应的方法参数
        Map<String, Parameter> parameters = this.applicationContext.getParameters(uri);
        Object[] paramValues = new Object[parameters.size()];
        String[] keys = parameters.keySet().toArray(new String[parameters.size()]);
        for (int index = 0, size = keys.length; index < size; index++) {

            //获取当前参数修饰信息
            String parameterName = keys[index];
            Parameter parameter = parameters.get(parameterName);

            //HttpServletRequest参数
            if (parameter.getType().equals(HttpServletRequest.class)) {
                paramValues[index] = request;
                continue;
            }

            //HttpServletResponse参数
            if (parameter.getType().equals(HttpServletResponse.class)) {
                paramValues[index] = response;
                continue;
            }

            //是否包含RequestParam注解
            if (parameter.isAnnotationPresent(RequestParam.class)) {

                //处理参数验证
                RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
                Object[] objects = request.getParameterMap().get(requestParam.value());
                if (requestParam.required()) {
                    if (objects == null || objects.length == 0) {
                        throw new RequestException(requestParam.value() + " can not to be null");
                    }
                }
            }

            //处理下整型，可以实现一个类型转换器
            Object[] objects = request.getParameterMap().get(parameterName);
            if (parameter.getType().equals(int.class) || parameter.getType().equals(Integer.class)) {
                paramValues[index] = Integer.valueOf(objects[0].toString());
            } else if (parameter.getType().equals(List.class)) {
                List list = new ArrayList<>(objects.length);
                Collections.addAll(list, objects);
                paramValues[index] = list;
            } else {
                paramValues[index] = objects[0].toString();
            }
        }

        //获取请求地址对应的方法映射
        Method method = this.applicationContext.getMethod(uri);
        String beanName = CaseConverter.toLowerCase(method.getDeclaringClass().getSimpleName());
        Object result = method.invoke(this.applicationContext.getBean(beanName), paramValues);
        if (result != null) {
            response.getResponseHeaders().add("Content-Type", "text/html; charset=UTF-8");
            response.write(result);
        }
    }

    @Override
    public void init(String contextConfigLocation) {
        super.init(contextConfigLocation);
        this.applicationContext = new WebApplicationContext(contextConfigLocation);
    }
}
